﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml.Serialization;
using System.Reflection;
using System.Globalization;
using System.Windows.Forms;

namespace OffInvoiceExcelTemplate
{
    public static class Validations
    {



        /// <summary>
        /// Enumerado de paises con los codigos iso en dos y tres letras
        /// </summary>
        public enum CountryType
        {

            [XmlEnumAttribute("AF")]
            AFG,

            [XmlEnumAttribute("AL")]
            ALB,

            [XmlEnumAttribute("AS")]
            ASM,

            [XmlEnumAttribute("AD")]
            AND,

            [XmlEnumAttribute("AO")]
            AGO,

            [XmlEnumAttribute("AI")]
            AIA,

            [XmlEnumAttribute("AG")]
            ATG,

            [XmlEnumAttribute("AR")]
            ARG,

            [XmlEnumAttribute("AM")]
            ARM,

            [XmlEnumAttribute("AW")]
            ABW,

            [XmlEnumAttribute("AU")]
            AUS,

            [XmlEnumAttribute("AT")]
            AUT,

            [XmlEnumAttribute("AZ")]
            AZE,

            [XmlEnumAttribute("BS")]
            BHS,

            [XmlEnumAttribute("BH")]
            BHR,

            [XmlEnumAttribute("BD")]
            BGD,

            [XmlEnumAttribute("BB")]
            BRB,

            [XmlEnumAttribute("BY")]
            BLR,

            [XmlEnumAttribute("BE")]
            BEL,

            [XmlEnumAttribute("BZ")]
            BLZ,

            [XmlEnumAttribute("BJ")]
            BEN,

            [XmlEnumAttribute("BM")]
            BMU,

            [XmlEnumAttribute("BT")]
            BTN,

            [XmlEnumAttribute("BO")]
            BOL,

            [XmlEnumAttribute("BA")]
            BIH,

            [XmlEnumAttribute("BW")]
            BWA,

            [XmlEnumAttribute("BR")]
            BRA,

            [XmlEnumAttribute("BN")]
            BRN,

            [XmlEnumAttribute("BG")]
            BGR,

            [XmlEnumAttribute("BF")]
            BFA,

            [XmlEnumAttribute("BI")]
            BDI,

            [XmlEnumAttribute("KH")]
            KHM,

            [XmlEnumAttribute("CM")]
            CMR,

            [XmlEnumAttribute("CA")]
            CAN,

            [XmlEnumAttribute("CV")]
            CPV,

            [XmlEnumAttribute("KY")]
            CYM,

            [XmlEnumAttribute("CF")]
            CAF,

            [XmlEnumAttribute("TD")]
            TCD,

            [XmlEnumAttribute("CL")]
            CHL,

            [XmlEnumAttribute("CN")]
            CHN,

            [XmlEnumAttribute("CD")]
            COD,

            [XmlEnumAttribute("CO")]
            COL,

            [XmlEnumAttribute("KM")]
            COM,

            [XmlEnumAttribute("CG")]
            COG,

            [XmlEnumAttribute("CK")]
            COK,

            [XmlEnumAttribute("CR")]
            CRI,

            [XmlEnumAttribute("CI")]
            CIV,

            [XmlEnumAttribute("CV")]
            HRV,

            [XmlEnumAttribute("CU")]
            CUB,

            [XmlEnumAttribute("CY")]
            CYP,

            [XmlEnumAttribute("CZ")]
            CZE,

            [XmlEnumAttribute("DZ")]
            DZA,

            [XmlEnumAttribute("DK")]
            DNK,

            [XmlEnumAttribute("DJ")]
            DJI,

            [XmlEnumAttribute("DM")]
            DMA,

            [XmlEnumAttribute("DO")]
            DOM,

            [XmlEnumAttribute("EC")]
            ECU,

            [XmlEnumAttribute("EG")]
            EGY,

            [XmlEnumAttribute("SV")]
            SLV,

            [XmlEnumAttribute("GQ")]
            GNQ,

            [XmlEnumAttribute("ER")]
            ERI,

            [XmlEnumAttribute("EE")]
            EST,

            [XmlEnumAttribute("ET")]
            ETH,

            [XmlEnumAttribute("FK")]
            FLK,

            [XmlEnumAttribute("FO")]
            FRO,

            [XmlEnumAttribute("FJ")]
            FJI,

            [XmlEnumAttribute("FI")]
            FIN,

            [XmlEnumAttribute("FR")]
            FRA,

            [XmlEnumAttribute("GF")]
            GUF,

            [XmlEnumAttribute("PF")]
            PYF,

            [XmlEnumAttribute("GA")]
            GAB,

            [XmlEnumAttribute("GM")]
            GMB,

            [XmlEnumAttribute("GE")]
            GEO,

            [XmlEnumAttribute("GG")]
            GGY,

            [XmlEnumAttribute("DE")]
            DEU,

            [XmlEnumAttribute("GH")]
            GHA,

            [XmlEnumAttribute("GI")]
            GIB,

            [XmlEnumAttribute("GR")]
            GRC,

            [XmlEnumAttribute("GL")]
            GRL,

            [XmlEnumAttribute("GD")]
            GRD,

            [XmlEnumAttribute("GP")]
            GLP,

            [XmlEnumAttribute("GU")]
            GUM,

            [XmlEnumAttribute("GT")]
            GTM,

            [XmlEnumAttribute("GN")]
            GIN,

            [XmlEnumAttribute("GW")]
            GNB,

            [XmlEnumAttribute("GY")]
            GUY,

            [XmlEnumAttribute("HT")]
            HTI,

            [XmlEnumAttribute("HN")]
            HND,

            [XmlEnumAttribute("HK")]
            HKG,

            [XmlEnumAttribute("HU")]
            HUN,

            [XmlEnumAttribute("IS")]
            ISL,

            [XmlEnumAttribute("IN")]
            IND,

            [XmlEnumAttribute("ID")]
            IDN,

            [XmlEnumAttribute("IM")]
            IMN,

            [XmlEnumAttribute("IR")]
            IRN,

            [XmlEnumAttribute("IQ")]
            IRQ,

            [XmlEnumAttribute("IE")]
            IRL,

            [XmlEnumAttribute("IL")]
            ISR,

            [XmlEnumAttribute("IT")]
            ITA,

            [XmlEnumAttribute("JM")]
            JAM,

            [XmlEnumAttribute("JE")]
            JEY,

            [XmlEnumAttribute("JP")]
            JPN,

            [XmlEnumAttribute("JO")]
            JOR,

            [XmlEnumAttribute("KZ")]
            KAZ,

            [XmlEnumAttribute("KE")]
            KEN,

            [XmlEnumAttribute("KI")]
            KIR,

            [XmlEnumAttribute("KP")]
            PRK,

            [XmlEnumAttribute("KR")]
            KOR,

            [XmlEnumAttribute("KW")]
            KWT,

            [XmlEnumAttribute("KG")]
            KGZ,

            [XmlEnumAttribute("LA")]
            LAO,

            [XmlEnumAttribute("LV")]
            LVA,

            [XmlEnumAttribute("LB")]
            LBN,

            [XmlEnumAttribute("LS")]
            LSO,

            [XmlEnumAttribute("LR")]
            LBR,

            [XmlEnumAttribute("EC")]
            LBY,

            [XmlEnumAttribute("LI")]
            LIE,

            [XmlEnumAttribute("LT")]
            LTU,

            [XmlEnumAttribute("LU")]
            LUX,

            [XmlEnumAttribute("MO")]
            MAC,

            [XmlEnumAttribute("MK")]
            MKD,

            [XmlEnumAttribute("MG")]
            MDG,

            [XmlEnumAttribute("MW")]
            MWI,

            [XmlEnumAttribute("MY")]
            MYS,

            [XmlEnumAttribute("MV")]
            MDV,

            [XmlEnumAttribute("ML")]
            MLI,

            [XmlEnumAttribute("MT")]
            MLT,

            [XmlEnumAttribute("LU")]
            MHL,

            [XmlEnumAttribute("MQ")]
            MTQ,

            [XmlEnumAttribute("MR")]
            MRT,

            [XmlEnumAttribute("MU")]
            MUS,

            [XmlEnumAttribute("YT")]
            MYT,

            [XmlEnumAttribute("MX")]
            MEX,

            [XmlEnumAttribute("FM")]
            FSM,

            [XmlEnumAttribute("MD")]
            MDA,

            [XmlEnumAttribute("MC")]
            MCO,

            [XmlEnumAttribute("ME")]
            MNE,

            [XmlEnumAttribute("MN")]
            MNG,

            [XmlEnumAttribute("MS")]
            MSR,

            [XmlEnumAttribute("MA")]
            MAR,

            [XmlEnumAttribute("MZ")]
            MOZ,

            [XmlEnumAttribute("MM")]
            MMR,

            [XmlEnumAttribute("NA")]
            NAM,

            [XmlEnumAttribute("NR")]
            NRU,

            [XmlEnumAttribute("NP")]
            NPL,

            [XmlEnumAttribute("NL")]
            NLD,

            [XmlEnumAttribute("AN")]
            ANT,

            [XmlEnumAttribute("NC")]
            NCL,

            [XmlEnumAttribute("NZ")]
            NZL,

            [XmlEnumAttribute("NI")]
            NIC,

            [XmlEnumAttribute("NE")]
            NER,

            [XmlEnumAttribute("NG")]
            NGA,

            [XmlEnumAttribute("NU")]
            NIU,

            [XmlEnumAttribute("NF")]
            NFK,

            [XmlEnumAttribute("MP")]
            MNP,

            [XmlEnumAttribute("NO")]
            NOR,

            [XmlEnumAttribute("OM")]
            OMN,

            [XmlEnumAttribute("PK")]
            PAK,

            [XmlEnumAttribute("PW")]
            PLW,

            [XmlEnumAttribute("PA")]
            PAN,

            [XmlEnumAttribute("PG")]
            PNG,

            [XmlEnumAttribute("PY")]
            PRY,

            [XmlEnumAttribute("PS")]
            PSE,

            [XmlEnumAttribute("PE")]
            PER,

            [XmlEnumAttribute("PH")]
            PHL,

            [XmlEnumAttribute("PN")]
            PCN,

            [XmlEnumAttribute("PL")]
            POL,

            [XmlEnumAttribute("PT")]
            PRT,

            [XmlEnumAttribute("PR")]
            PRI,

            [XmlEnumAttribute("QA")]
            QAT,

            [XmlEnumAttribute("RE")]
            REU,

            [XmlEnumAttribute("RO")]
            ROU,

            [XmlEnumAttribute("RU")]
            RUS,

            [XmlEnumAttribute("RW")]
            RWA,

            [XmlEnumAttribute("KN")]
            KNA,

            [XmlEnumAttribute("LC")]
            LCA,

            [XmlEnumAttribute("VC")]
            VCT,

            [XmlEnumAttribute("WS")]
            WSM,

            [XmlEnumAttribute("SM")]
            SMR,

            [XmlEnumAttribute("ST")]
            STP,

            [XmlEnumAttribute("SA")]
            SAU,

            [XmlEnumAttribute("SN")]
            SEN,

            [XmlEnumAttribute("RS")]
            SRB,

            [XmlEnumAttribute("SC")]
            SYC,

            [XmlEnumAttribute("SL")]
            SLE,

            [XmlEnumAttribute("SG")]
            SGP,

            [XmlEnumAttribute("SK")]
            SVK,

            [XmlEnumAttribute("SI")]
            SVN,

            [XmlEnumAttribute("SB")]
            SLB,

            [XmlEnumAttribute("SO")]
            SOM,

            [XmlEnumAttribute("ZA")]
            ZAF,

            [XmlEnumAttribute("ES")]
            ESP,

            [XmlEnumAttribute("LK")]
            LKA,

            [XmlEnumAttribute("SH")]
            SHN,

            [XmlEnumAttribute("PM")]
            SPM,

            [XmlEnumAttribute("SD")]
            SDN,

            [XmlEnumAttribute("SR")]
            SUR,

            [XmlEnumAttribute("SJ")]
            SJM,

            [XmlEnumAttribute("SZ")]
            SWZ,

            [XmlEnumAttribute("SE")]
            SWE,

            [XmlEnumAttribute("CH")]
            CHE,

            [XmlEnumAttribute("SY")]
            SYR,

            [XmlEnumAttribute("TW")]
            TWN,

            [XmlEnumAttribute("TJ")]
            TJK,

            [XmlEnumAttribute("TZ")]
            TZA,

            [XmlEnumAttribute("TH")]
            THA,

            [XmlEnumAttribute("TG")]
            TGO,

            [XmlEnumAttribute("TK")]
            TKL,

            [XmlEnumAttribute("TO")]
            TON,

            [XmlEnumAttribute("TT")]
            TTO,

            [XmlEnumAttribute("TN")]
            TUN,

            [XmlEnumAttribute("TR")]
            TUR,

            [XmlEnumAttribute("TM")]
            TKM,

            [XmlEnumAttribute("TL")]
            TLS,

            [XmlEnumAttribute("TC")]
            TCA,

            [XmlEnumAttribute("TV")]
            TUV,

            [XmlEnumAttribute("UG")]
            UGA,

            [XmlEnumAttribute("UA")]
            UKR,

            [XmlEnumAttribute("AE")]
            ARE,

            [XmlEnumAttribute("GB")]
            GBR,

            [XmlEnumAttribute("US")]
            USA,

            [XmlEnumAttribute("UY")]
            URY,

            [XmlEnumAttribute("UZ")]
            UZB,

            [XmlEnumAttribute("VU")]
            VUT,

            [XmlEnumAttribute("VA")]
            VAT,

            [XmlEnumAttribute("VE")]
            VEN,

            [XmlEnumAttribute("VN")]
            VNM,

            [XmlEnumAttribute("VG")]
            VGB,

            [XmlEnumAttribute("VI")]
            VIR,

            [XmlEnumAttribute("WL")]
            WLF,

            [XmlEnumAttribute("EH")]
            ESH,

            [XmlEnumAttribute("YE")]
            YEM,

            [XmlEnumAttribute("ZM")]
            ZMB,

            [XmlEnumAttribute("ZW")]
            ZWE,
        }

        /// <summary>
        /// Método que valida la estructura de una direccion de correo electrónico
        /// </summary>
        /// <param name="email">Parámetro de tipo string que contiene la dirección a validar</param>
        /// <returns></returns>
        public static bool ValidarEmail(string email)
        {
            string expresion = "\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*";

            if (Regex.IsMatch(email, expresion))
            {
                if (Regex.Replace(email, expresion, String.Empty).Length == 0)
                { return true; }
                else
                { return false; }
            }
            else
            { return false; }
        }

        private static bool ValidarCIF(string cif)
        {
            //Si la letra inicial del CIF es una de estas el digito de control es un numero
            //string digitoControlNum = "ABDEFGHJUV";
            //Si la letra inicial del CIF es una de estas el digito de control es una letra
            string digitoControlLetra = "CKLMNPQRSW";
            //Posibles letras iniciales
            string letras = "ABCDEFGHJKLMNPQRSUVW";
            string digitoControl = string.Empty;
            int pares = 0;
            int impares = 0;
            bool esLetra = false;
            string letraInicial = cif.Substring(0, 1);
            //Comprobacion de longitud
            if (cif.Length != 9)
            {
                Console.WriteLine("El Cif debe tener 9 dígitos");
                return false;
            }
            //Comprobacion de letra incial
            if (letras.IndexOf(letraInicial.ToUpper()) == -1)
            {
                Console.WriteLine("El comienzo del Cif no es válido");
                return false;
            }
            //Comprobacion de los 7 digitos numéricos
            if (!IsNumeric(cif.Substring(1, 7)))
            {
                Console.WriteLine("El CIF contiene caracteres no validos");
                return false;
            }
            //Comprobación para saber si el digito de control es un numero o una letra
            if (digitoControlLetra.Contains(letraInicial.ToUpper()))
            {
                esLetra = true;
            }
            //Suma de los numeros que estan en las posiciones pares
            for (int i = 2; i < 8; i++)
            {
                pares = pares + int.Parse(cif.Substring(i, 1));
                i++;
            }
            //Suma de los numeros que estan en las posiciones impare
            //Por cada numero de una posicion impar se multiplica por 2 y se suman las cifras del resultado entre si
            for (int i = 1; i < 9; i++)
            {
                int nn = 2 * int.Parse(cif.Substring(i, 1));
                if (nn > 9) nn = 1 + (nn - 10);
                impares = impares + nn;
                i++;
            }
            //Calculo del digito de control
            //Se suman los pares e impares,se coge el digito de las unidades del resultado y se le resta a 10
            //Ese digito será un valor del 0 al 9 en el caso de ser numerico o de la A a la J
            //en el caso de ser una letra.
            int parcial = pares + impares;
            int control = (10 - (parcial % 10)) % 10;
            //if (control == 10)
            //    control = 0;
            if (esLetra)
            {
                string[] l = { "J", "A", "B", "C", "D", "E", "F", "G", "H", "I" };
                digitoControl = l[control];
            }
            else
            {
                digitoControl = control.ToString();
            }
            //Comrobación del digito de control
            if (digitoControl != cif.Substring(8, 1).ToUpper())
            {
                Console.WriteLine("El Cif no es válido");
                return false;
            }
            Console.WriteLine("Cif valido");
            return true;
        } 

        /// <summary>
        /// Método que valida si un string es un numero o no
        /// </summary>
        /// <param name="num">Parámetro de tipo string que contiene el numero a validar</param>
        /// <returns></returns>
        public static bool IsNumeric(string num)
        {
            try
            {
                int.Parse(num);
                return true;
            }
            catch (Exception)
            {
                return false;

            }
        }

        /// <summary>
        /// Método que validad el DNI
        /// </summary>
        /// <param name="dni">Parámetro de tipo string que contiene el DNI a validar</param>
        /// <returns></returns>
        private static bool ValidarDNI(string dni)
        {

            if (new Regex("[0-9]{8}[A-Za-z]").Match(dni).Success)
            {
                return ("TRWAGMYFPDXBNJZSQVHLCKE"[(int)long.Parse(dni.Substring(0, 8)) % 23].ToString() == dni.Substring(8).ToString().ToUpper());
            }
            else
            {
                return false;
            }


        }

        /// <summary>
        /// Convierte un string en un elemento del enumerado de paises cuyo nombre corresponda
        /// </summary>
        /// <param name="country">nombre del enumerado</param>
        /// <returns>enumerado con nombre = country</returns>
        public static CountryType convertToCountryType(string country)
        {
            try
            {
                return (CountryType)Enum.Parse(typeof(CountryType), country);
            }
            catch (Exception ex)
            {
                throw ex;

            }
        }

        /// <summary>
        /// Devulve el atributo name de un enumerado
        /// </summary>
        /// <param name="e">enumerado del que se quiere conocer el atributto name</param>
        /// <returns>valor del atributo name</returns>
        public static string ConvertToString(Enum e)
        {
            // Get the Type of the enum
            Type t = e.GetType();

            // Get the FieldInfo for the member field with the enums name
            FieldInfo info = t.GetField(e.ToString("G"));

            // Check to see if the XmlEnumAttribute is defined on this field
            if (!info.IsDefined(typeof(XmlEnumAttribute), false))
            {
                // If no XmlEnumAttribute then return the string version of the enum.
                return e.ToString("G");
            }

            // Get the XmlEnumAttribute
            object[] o = info.GetCustomAttributes(typeof(XmlEnumAttribute), false);
            XmlEnumAttribute att = (XmlEnumAttribute)o[0];
            return att.Name;
        }

        /// <summary>
        /// utilizado para validacion de nif, cif y nif en formato europeo
        /// </summary>
        /// <param name="cif">identificador fiscal</param>
        /// <param name="country">pais de resindencia del titular del cif</param>
        /// <returns>true si el cif pasa la validacion</returns>
        private static bool validarCif(string cif, string country)
        {
            bool valido = false;
            bool countryvalido = false;
            bool idvalido = false;

            if (string.IsNullOrEmpty(cif))
            {
                throw new Exception("no se ha indicado un cif/nif valido");
            }
            else if (cif.Length == 11)
            {
                string countrycode = cif.Substring(0, 2);
                string nif = cif.Substring(2);
                countryvalido = validarCountryCode(country, countrycode);

                char[] c1 = nif.ToCharArray();
                if (!Char.IsDigit(c1[0]))
                {
                    idvalido = Validations.ValidarCIF(nif);
                }
                else
                {
                    idvalido = Validations.ValidarDNI(nif);
                }

                if (countryvalido && idvalido)
                    valido = true;
            }
            else
            {
                if (!Char.IsDigit(cif.ToCharArray()[0]))
                {
                    valido = Validations.ValidarCIF(cif);
                }
                else
                {
                    valido = Validations.ValidarDNI(cif);
                }
            }
            return valido;


        }

        /// <summary>
        /// valida si el codigo de pais en dos letras corresponde al de tres  letras
        /// </summary>
        /// <param name="countrycode3">codigo de pais en tres letras</param>
        /// <param name="countrycode2">codigo de pais en dos letras</param>
        public static bool validarCountryCode(string countrycode3, string countrycode2)
        {
            bool valido = false;
            CountryType country2;
            try
            {
                country2 = convertToCountryType(countrycode3);
                string code = ConvertToString(country2);
                if (countrycode2.ToUpper().Equals(code))
                {
                    valido = true;
                }
            }
            catch (Exception ex)
            {
            }
            return valido;
        }

        public static string validarCif(bool cifvalidation, string country, string Cif)
        {
            if (string.IsNullOrEmpty(country) && !cifvalidation)
            {
                throw new Exception("countrynotinlist");
            }
            else
            {
                try
                {
                    if (Validations.validarCif(Cif, country))
                    {
                        if (Cif.Length == 9)
                        {
                            string country2 = Validations.ConvertToString(Validations.convertToCountryType(country));
                            Cif = string.Concat(country2, Cif);
                        }
                    }
                    else
                    {
                        throw new Exception("ErrorInvalidCIF");
                    }
                }
                catch (Exception ex)
                {

                    throw ex;
                }
            }

            return Cif;
        }

    
    }
}
